#pragma once
#include <sw/redis++/redis.h>
#include <iostream>
#include <thread>
#include <chrono>
#include <memory>
#include "logger.hpp"

namespace bite_im {
    class RedisClientFactory
    {
        public:
        static std::shared_ptr<sw::redis::Redis> create(
            const std::string &host,
            int port,
            int db,
            bool keep_alive)
        {
            sw::redis::ConnectionOptions opts;
            opts.host = host;
            opts.port = port;
            opts.db = db;
            opts.keep_alive = keep_alive;
            auto res = std::make_shared<sw::redis::Redis>(opts);
            return res;
        }
    };
    class Session
    {
        public:
        Session(std::shared_ptr<sw::redis::Redis> client):
            _client(client) {}
        bool append(const std::string &ssid, const std::string &uid)
        {
            try {
                _client->set(ssid, uid);
            } catch (const sw::redis::Error &e) {
                LOG_ERROR("创建会话失败: {}", e.what());
                return false;
            }
            return true;
        }
        bool remove(const std::string &ssid)
        {
            try {
                _client->del(ssid);
            } catch (const sw::redis::Error &e) {
                LOG_ERROR("删除会话失败: {}", e.what());
                return false;
            }
            return true;
        }
        std::string get_uid(const std::string &ssid)
        {
            try {
                auto res = _client->get(ssid);
                if (res) {
                    return *res;
                } else {
                    return "";
                }
            } catch (const sw::redis::Error &e) {
                LOG_ERROR("获取会话失败: {}", e.what());
                return "";
            }
        }
        private:
        std::shared_ptr<sw::redis::Redis> _client;
    };

    class VerifyCode
    {
        public:
        VerifyCode(std::shared_ptr<sw::redis::Redis> client):
            _client(client) {}
        bool append(const std::string &cid, const std::string &code)
        {
            try {
                _client->set(cid, code, std::chrono::milliseconds(300000));
            } catch (const sw::redis::Error &e) {
                LOG_ERROR("添加验证码失败: {}", e.what());
                return false;
            }
            return true;
        }
        bool remove(const std::string &cid)
        {
            try {
                _client->del(cid);
            } catch (const sw::redis::Error &e) {
                LOG_ERROR("删除验证码失败: {}", e.what());
                return false;
            }
            return true;
        }   
        std::string get_code(const std::string &cid)
        {
            try {
                auto res = _client->get(cid);
                if (res) {
                    return *res;
                } else {
                    return "";
                }
            } catch (const sw::redis::Error &e) {
                LOG_ERROR("获取验证码失败: {}", e.what());
                return "";
            }
        }
        private:
        std::shared_ptr<sw::redis::Redis> _client;
    };
    class LoginStatus
    {
        public:
        LoginStatus(std::shared_ptr<sw::redis::Redis> client):
            _client(client) {}
        bool append(const std::string &uid)
        {
            try {
                _client->set(uid, "");
            } catch (const sw::redis::Error &e) {
                LOG_ERROR("添加登录状态失败: {}", e.what());
                return false;
            }
            return true;
        }   
        bool remove(const std::string &uid)
        {
            try {
                _client->del(uid);
            } catch (const sw::redis::Error &e) {
                LOG_ERROR("删除登录状态失败: {}", e.what());
                return false;
            }
            return true;
        }
        bool exists(const std::string &uid)
        {
            try {
                auto res = _client->get(uid);
                if (res) {
                    return true;
                } else {
                    return false;   
                }
            } catch (const sw::redis::Error &e) {
                LOG_ERROR("查询登录状态失败: {}", e.what());
                return false;
            }
        }
        private:
        std::shared_ptr<sw::redis::Redis> _client;
    };
}